package cn.enilu.flash.api.controller.h5;

import cn.enilu.flash.bean.entity.order.PayOrder;
import cn.enilu.flash.bean.entity.system.User;
import cn.enilu.flash.bean.entity.task.HelpTask;
import cn.enilu.flash.bean.entity.task.MoneyInfo;
import cn.enilu.flash.bean.vo.front.Ret;
import cn.enilu.flash.bean.vo.front.Rets;
import cn.enilu.flash.bean.vo.query.SearchFilter;
import cn.enilu.flash.security.JwtUtil;
import cn.enilu.flash.service.order.PayOrderService;
import cn.enilu.flash.service.system.CfgService;
import cn.enilu.flash.service.system.UserService;
import cn.enilu.flash.service.task.HelpTaskService;
import cn.enilu.flash.service.task.MoneyInfoService;
import cn.enilu.flash.utils.HttpUtil;
import cn.enilu.flash.utils.JsonUtil;
import cn.enilu.flash.utils.StringUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@RequestMapping("/h5")
@RestController
public class H5PayController {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private UserService userService;

    @Autowired
    private HelpTaskService taskService;

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private CfgService cfgService;

    @Autowired
    private MoneyInfoService moneyInfoService;

    /**
     * 发布任务支付接口，若为余额支付，支付成功返回任务ID
     * @param taskId 任务id
     * @param payType 支付类型：1.余额支付，2.微信支付
     * @return
     */
    @PostMapping("/pay")
    @ApiOperation("任务支付接口：支付成功返回任务ID")
    public Ret pay(Long taskId,@ApiParam("支付类型：1.余额支付，2.微信支付") Integer payType){
        if(StringUtil.isNullOrEmpty(taskId)){
            logger.info("任务ID为空！");
            return Rets.failure("任务异常啦");
        }
        if(StringUtil.isNullOrEmpty(payType)){
            logger.info("支付类型为空！");
            return Rets.failure("请选择支付类型！");
        }
        HelpTask helpTask = taskService.get(taskId);
        if(StringUtil.isNullOrEmpty(helpTask)){
            return Rets.failure("任务异常啦");
        }
        if(helpTask.getCreateBy()!=JwtUtil.getUserId()){
            return Rets.failure("只能支付自己的任务");
        }
        PayOrder payOrder = payOrderService.get(new SearchFilter("taskId", SearchFilter.Operator.EQ, taskId));
        if(payOrder!=null) return Rets.failure("订单已支付！");
        Map<String, BigDecimal> costMap = getCostMap(helpTask);
        if(StringUtil.isNotNullOrEmpty(payType)){
            if(payType == 1){
                User user = userService.get(JwtUtil.getUserId());
                BigDecimal balance = user.getBalance() == null ?BigDecimal.ZERO:user.getBalance();
                if(balance.compareTo(costMap.get("totalCost"))<0){
                    return Rets.failure("余额不足！");
                }
                helpTask = insertPayOrder(taskId,null,costMap.get("totalCost"),user.getId(),1);// 插入支付信息、变动金额、把任务状态设为待审核
                return helpTask == null ?Rets.failure("支付失败！"):Rets.success(taskId);
            }else { // 微信支付,生成微信支付参数  // TODO
                return getH5PayUrl(costMap.get("totalCost"),"任务发布-["+helpTask.getTitle()+"]","taskId"+helpTask.getId());
            }
        }
        return Rets.failure("支付失败！");
    }

    /**
     * 支付VIP
     * @param type 会员类型 1月会员 2季会员 3年会员
     * @return
     */
    @PostMapping("/payVip")
    public Ret payVip(Integer type,@ApiParam("支付类型：1.余额支付，2.微信支付") Integer payType){
        BigDecimal payMoney = BigDecimal.ZERO;
        if(type == 1){
            String cfgValue = cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, "monthVip")).getCfgValue();
            payMoney = new BigDecimal(cfgValue);
        }else if(type == 2){
            String cfgValue = cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, "seasonVip")).getCfgValue();
            payMoney = new BigDecimal(cfgValue);
        }else if(type == 3){
            String cfgValue = cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, "yearVip")).getCfgValue();
            payMoney = new BigDecimal(cfgValue);
        }
        User user = userService.get(JwtUtil.getUserId());
        BigDecimal balance = user.getBalance() == null ?BigDecimal.ZERO:user.getBalance();
        if(payType == 1){
            if(balance.compareTo(payMoney)<0){
                return Rets.failure("余额不足！");
            }
            insertPayOrder(null,type,payMoney,user.getId(),1);
        }else {
            if(type == 1)return getH5PayUrl(payMoney,"月Vip","monthVip"+new Date().getTime()/1000);
            if(type == 2)return getH5PayUrl(payMoney,"季Vip","seasonVip"+new Date().getTime()/1000);
            if(type == 3)return getH5PayUrl(payMoney,"年Vip","yearVip"+new Date().getTime()/1000);
        }
        return Rets.success();
    }

    /**
     * 微信回调函数
     * @return
     */
    @RequestMapping("/payCallBack")
    public int payCallBack(HttpServletRequest request, HttpServletResponse response){
        // 验证是否支付成功 //TODO
        Long taskId = -1l;// 若已支付,获取任务id
        Long userId = -1l;// 获取用户Id
        HelpTask helpTask = taskService.get(taskId);
        Map<String, BigDecimal> costMap = getCostMap(helpTask);
        BigDecimal payMoney = costMap.get("totalCost");// 总费用
        helpTask = insertPayOrder(taskId,null,payMoney,helpTask.getCreateBy(),2); // 插入支付信息、变动金额、把任务状态设为待审核
        return 200;// 告诉微信已通知成功
    }


    /**
     *  插入支付信息并把任务状态设为待审核
     * @param taskId
     * @return
     */
    private HelpTask insertPayOrder(Long taskId,Integer vipType,BigDecimal payMoney,Long userId,Integer payType){
        HelpTask helpTask = null;
        PayOrder payOrder = new PayOrder();
        Map<String, BigDecimal> costMap = null;
        if(taskId != null){
            helpTask = taskService.get(taskId);
            if(helpTask == null) return null;
            costMap = getCostMap(helpTask);
            payOrder.setBrokerage(costMap.get("brokerage"));
            payOrder.setTotalServiceFee(costMap.get("totalServiceFee"));
        }else {
            payOrder.setBrokerage(BigDecimal.ZERO);
            payOrder.setTotalServiceFee(payMoney);
        }
        payOrder.setPayType(payType); // 支付类型
        payOrder.setCreateBy(JwtUtil.getUserId());
        payOrder.setTaskId(taskId);
        PayOrder insert = payOrderService.insert(payOrder);
        if(StringUtil.isNotNullOrEmpty(insert)){
            if(taskId != null){
                helpTask.setState(2);// 待审核
                helpTask = taskService.update(helpTask);// 保存信息
            }
        }
        if(payType == 2){ // 微信支付需要先添加充值记录
            moneyInfoService.setMoneyInfo(taskId,userId,5,payMoney); // 设置金额明细并变动用户金额
        }
        if(vipType != null){ // vip支付
            if(vipType == 1)moneyInfoService.setMoneyInfo(taskId,userId,6,payMoney);// 月vip
            if(vipType == 2)moneyInfoService.setMoneyInfo(taskId,userId,7,payMoney);// 季vip
            if(vipType == 3)moneyInfoService.setMoneyInfo(taskId,userId,8,payMoney);// 年vip
        }else {
            moneyInfoService.setMoneyInfo(taskId,userId,3,payMoney); // 设置金额明细并变动用户金额
        }

        return helpTask;
    }

    /**
     * 任务费用
     * @param helpTask
     * @return
     */
    private Map<String,BigDecimal> getCostMap(HelpTask helpTask){
        Integer num = helpTask.getNum();
        Map<String,BigDecimal> map = new LinkedHashMap<>();
        BigDecimal price = helpTask.getPrice();                                // 任务单价
        map.put("price",price);
        BigDecimal brokerage = price.multiply(new BigDecimal(num));            // 总任务佣金
        map.put("brokerage",brokerage);
        BigDecimal serviceFee = helpTask.getServiceFee();                      // 单个任务服务费
        map.put("serviceFee",serviceFee);
        BigDecimal totalServiceFee = serviceFee.multiply(new BigDecimal(num)); // 总服务费
        map.put("totalServiceFee",totalServiceFee);
        BigDecimal totalCost = brokerage.add(totalServiceFee);                 // 总费用
        map.put("totalCost",totalCost);
        return map;
    }
    private Ret getH5PayUrl(BigDecimal payMoney,String description,String out_trade_no){
        Map<String,Object> map = new LinkedHashMap<>();             // 调用H5微信支付所需参数
        Map<String,Object> amount = new LinkedHashMap<>();          // 存放订单金额信息
        amount.put("total",payMoney.intValue()*100);// 支付金额 单位 分
        Map<String,Object> scene_info = new LinkedHashMap<>();      // 存放支付场景描述
        scene_info.put("payer_client_ip",HttpUtil.getIp());         //用户的客户端IP，支持IPv4和IPv6两种格式的IP地址。
        Map<String,Object> h5_info = new LinkedHashMap<>();
        h5_info.put("type","Wap");                                  //iOS, Android, Wap
        scene_info.put("h5_info",h5_info);                          //用户的客户端IP，支持IPv4和IPv6两种格式的IP地址。
        map.put("appid","wx45xxxxxxxxxx");                          // 由微信生成的应用ID，全局唯一
        map.put("mchid","1111111");// 商户号
        map.put("description",description);      // 商品描述
        map.put("out_trade_no",out_trade_no);                   // 商户订单号
        map.put("notify_url","https://www.xxx.com/pay/payCallBack");// 回调地址,必须是https地址
        map.put("amount",amount);                                  //订单金额信息
        map.put("scene_info",scene_info);                          // 支付场景描述
        String responseStr = HttpUtil.sendPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5", JsonUtil.toJson(map));
        if(!responseStr.contains("h5_url")) return Rets.failure("支付失败！"); // 正确返回有h5_url字段，如果没有则请求微信支付失败
        Map responseMap = JsonUtil.fromJson(Map.class, responseStr);
        String h5_url = (String) responseMap.get("h5_url");
        return Rets.success(h5_url);
    }

}
